package org.example;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Scanner;

public class BejeweledGame extends JPanel implements ActionListener {
    private static final int H = 13;  // 网格的行数（高度）
    private static final int W = 6;   // 网格的列数（宽度）
    private static final int JH = 3;  // 下落宝石的高度（即一次性可以下落的宝石数量）
    private static final int JW = 1;  // 下落宝石的宽度（这里固定为1，表示每次只在一列上下落）
    private static final int TILE_SIZE = 40;  // 每个网格的大小
    private static final int PADDING = 10;    // 边距

    private char[][] table = new char[H + 1][W + 1];
    private char[][] newJewels = new char[JH][JW];
    private boolean[][] isW = new boolean[H][W];
    private boolean flag;

    private Timer timer;

    public BejeweledGame() {
        setPreferredSize(new Dimension((W + 1) * TILE_SIZE + 2 * PADDING, (H + 1) * TILE_SIZE + 2 * PADDING));
        setBackground(Color.WHITE);
        timer = new Timer(500, this);  // 定时器，每500毫秒触发一次动作事件
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                char jewel = table[i][j];
                // 使用 (int) (Math.random() * 256) 来生成 0 到 255 之间的随机整数
                // 注意：这种方法有时会产生 255，但永远不会产生负值
                // 如果需要更精确地控制颜色分布，可以使用 (int) Math.round(Math.random() * 255)
                Color color = jewel == 'W' ? Color.WHITE : new Color((int) (Math.random() * 256), (int) (Math.random() * 256), (int) (Math.random() * 256));
                g.setColor(color);
                g.fillRect(j * TILE_SIZE + PADDING, i * TILE_SIZE + PADDING, TILE_SIZE, TILE_SIZE);
                g.setColor(Color.BLACK);
                g.drawRect(j * TILE_SIZE + PADDING, i * TILE_SIZE + PADDING, TILE_SIZE, TILE_SIZE);
                if (jewel != 'W') {
                    g.drawString(String.valueOf(jewel), j * TILE_SIZE + PADDING + 10, i * TILE_SIZE + PADDING + 25);
                }
            }
        }
    }

    private void downOp() {
        for (int j = 0; j < W; j++) {
            int x = H - 1;
            for (int i = H - 1; i >= 0; i--) {
                if (isW[i][j]) continue;
                table[x--][j] = table[i][j];
            }
            for (int i = x; i >= 0; i--) table[i][j] = 'W';
        }
    }

    private void search() {
        flag = true;
        memsetIsW();
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                if (table[i][j] != 'W') {
                    for (int k = 0; k < 8; k++) {
                        int ni = i + 2 * dir[k][0];
                        int nj = j + 2 * dir[k][1];
                        if (ni >= 0 && ni < H && nj >= 0 && nj < W) {
                            if (table[i + dir[k][0]][j + dir[k][1]] == table[i][j] && table[ni][nj] == table[i][j]) {
                                int t = 0;
                                while (i + t * dir[k][0] >= 0 && i + t * dir[k][0] < H && j + t * dir[k][1] >= 0 && j + t * dir[k][1] < W
                                        && table[i + t * dir[k][0]][j + t * dir[k][1]] == table[i][j]) {
                                    isW[i + t * dir[k][0]][j + t * dir[k][1]] = true;
                                    t++;
                                }
                                flag = false;
                            }
                        }
                    }
                }
            }
        }
        if (!flag) {
            downOp();
            repaint();
        }
    }

    private void memsetIsW() {
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                isW[i][j] = false;
            }
        }
    }

    private int[][] dir = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, -1 }, { -1, 1 }, { 1, 1 }, { 1, -1 } };

    public void loadGame(String[] initialTable, String[] newJewelsStr, int column) {
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                table[i][j] = initialTable[i].charAt(j);
            }
        }
        for (int i = 0; i < JH; i++) {
            newJewels[i][0] = newJewelsStr[i].charAt(0);
        }
        int h = H - 1;
        for (int i = H - 1; i >= 0; i--) {
            if (table[i][column] == 'W') {
                h = i;
                break;
            }
        }
        for (int i = h - JH + 1; i <= h; i++) {
            table[i][column] = newJewels[i - (h - JH + 1)][0];
        }
        flag = false;
        while (!flag) {
            search();
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // 在这个简单的示例中，我们不会持续自动下落宝石，
        // 而是通过点击按钮来触发搜索和下落操作。
        // 这里定时器仅作为示例保留。
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int T = scanner.nextInt();
        scanner.nextLine();  // Consume newline

        JFrame frame = new JFrame("Bejeweled Game");
        BejeweledGame game = new BejeweledGame();
        frame.add(game);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);

        JButton dropButton = new JButton("Drop Jewels");
        dropButton.addActionListener(e -> {
            for (int t = 0; t < T; t++) {
                String[] initialTable = new String[H];
                for (int i = 0; i < H; i++) {
                    initialTable[i] = scanner.nextLine();
                }
                String[] newJewelsStr = new String[JH];
                for (int i = 0; i < JH; i++) {
                    newJewelsStr[i] = scanner.next();
                }
                int column = scanner.nextInt() - 1;
                scanner.nextLine();  // Consume newline

                game.loadGame(initialTable, newJewelsStr, column);
            }
        });

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(dropButton);
        frame.add(buttonPanel, BorderLayout.SOUTH);

        frame.setVisible(true);
        scanner.close();
    }
}